﻿using System;
using System.IO;
using System.Xml.Serialization;
using System.Text;
using System.Xml;

namespace Shine.Util.Serialization
{
    /// <summary>
    /// 概述：提供 XML 的序列化和反序列化实现<br />
    /// </summary>
    public class XmlSerialization
    {
        /// <summary>
        /// 序列化一个实例到字节数组（泛型）。
        /// </summary>
        /// <typeparam name="T">要序列化的实例的类型。</typeparam>
        /// <param name="o">要序列化的实例。</param>
        /// <returns>序列化实例得到的字节数组。</returns>
        public static byte[] Serialize<T>(object o)
        {
            if (o == null)
            {
                return null;
            }

            using (MemoryStream memoryStream = new MemoryStream())
            {
                new XmlSerializer(typeof(T)).Serialize(memoryStream, o);
                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// 序列化一个实例到文件。
        /// </summary>
        /// <typeparam name="T">要序列化的实例的类型。</typeparam>
        /// <param name="path">文件路径。</param>
        /// <param name="o">要序列化的实例。</param>
        /// <param name="extraTypes">要序列化的其他对象类型的 System.Type 数组。</param>
        public static void Serialize<T>(string path, object o, Type[] extraTypes = null)
        {
            if (o == null)
            {
                return;
            }
            FileInfo fi = new FileInfo(path);
            if (!Directory.Exists(fi.DirectoryName))
                Directory.CreateDirectory(fi.DirectoryName);
            using (FileStream fileStream = new FileStream(path, FileMode.Create))
            {
                new XmlSerializer(typeof(T), extraTypes).Serialize(fileStream, o);
            }
        }

        /// <summary>
        /// 从字节数组反序列化一个实例（泛型）。
        /// </summary>
        /// <typeparam name="T">反序列化得到的实例的类型。</typeparam>
        /// <param name="bytes">要反序列化的字节数组。</param>
        /// <returns>反序列化得到的实例。</returns>
        public static object Deserialize<T>(byte[] bytes)
        {
            if (bytes == null)
            {
                return null;
            }

            using (MemoryStream memoryStream = new MemoryStream(bytes))
            {
                return new XmlSerializer(typeof(T)).Deserialize(memoryStream);
            }
        }

        /// <summary>
        /// 从文件反序列化一个实例（泛型）。
        /// </summary>
        /// <typeparam name="T">反序列化得到的实例的类型。</typeparam>
        /// <param name="path">文件路径。</param>
        /// <param name="extraTypes">要反序列化的其他对象类型的 System.Type 数组。</param>
        /// <returns>反序列化得到的实例。</returns>
        public static object Deserialize<T>(string path, Type[] extraTypes = null)
        {
            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                return new XmlSerializer(typeof(T), extraTypes).Deserialize(fileStream);
            }
        }

        /// <summary>
        /// 将指定的对象序列化到Xml
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">要序列化的对象</param>
        /// <returns></returns>
        public static string ToXml<T>(T obj)
        {
            XmlSerializer ser = new XmlSerializer(obj.GetType());
            StringBuilder sb = new StringBuilder();
            using (XmlWriter writer = XmlWriter.Create(sb))
            {
                ser.Serialize(writer, obj);
                return sb.ToString();
            }
        }

        /// <summary>
        /// 将xml反序列化成对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="xml">xml字符串</param>
        /// <returns></returns>
        public static T FromXml<T>(string xml)
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            using (XmlReader reader = new XmlTextReader(new StringReader(xml)))
            {
                return (T)ser.Deserialize(reader);
            }
        }
    }
}